﻿/*******************************************************************************
 * New BSD License (BSD)
 * 
 * Copyright (c) 2012, Stanislav Zhelnio
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification, are permitted 
 * provided that the following conditions are met:
 * - Redistributions of source code must retain the above copyright notice, this list of conditions 
 *   and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions 
 *   and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * For project details see http://tambourinenunit.codeplex.com/
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;

namespace Tambourine.NUnit.UseExample
{
    public class TambourineUse
    {
        //some foreign code library
        public class BlackBox
        {
            public int i { get; private set; }
            public int j { get; private set; }

            //the uncknown bug/feature in foreign code
            private int x;

            public void LoadDataFirstWay() { i = 0; j = 0; x = 0; }
            public void LoadDataSecondWay() { i = 0; j = 0; x = 0; }

            public void UpdataDataFirstWay() { i++; j++; }
            public void UpdateDataSecondWay() { i++; j++; }

            //methods with bug/feature
            public void UpdateDataThirdWay() { i++; j++; j += x; }
            public void UpdateDataFourthWay() { i++; j++; x++; }
        }

        //Black box test helper cover
        public class Operation
        { 
            public void Run(string operationName)
            {
                if (operationName == null)
                    return;

                Type type = this.GetType();
                MethodInfo method = type.GetMethod(operationName);
                method.Invoke(this, null);
            }

            BlackBox box = new BlackBox();

            public void LoadDataFirstWay() { box.LoadDataFirstWay(); }
            public void LoadDataSecondWay() { box.LoadDataSecondWay(); }

            public void UpdataDataFirstWay() { box.UpdataDataFirstWay(); }
            public void UpdateDataSecondWay() { box.UpdateDataSecondWay(); }
            public void UpdateDataThirdWay() { box.UpdateDataThirdWay(); }
            public void UpdateDataFourthWay() { box.UpdateDataFourthWay(); }

            public void checkDataResultChangedI() { Assert.That(box.i > 0); }
            public void checkDataResultChangedJ() { Assert.That(box.j > 0); }
            public void checkDataResultSingleOperationI() { Assert.That(box.i == 1); }
            public void checkDataResultSingleOperationJ() { Assert.That(box.j == 1); }
            public void checkDataResultPairOperationI() { Assert.That(box.i == 2); }
            public void checkDataResultPairOperationJ() { Assert.That(box.j == 2); }
            public void checkDataResultThreeOperationI() { Assert.That(box.i == 3); }
            public void checkDataResultThreeOperationJ() { Assert.That(box.j == 3); }
        }

        [Test, Combinatorial]
        [Property("TambourineArguments", "loadMethod,updateMethod,checkMethod")]
        [Property("TambourineColumn", "checkMethod")]
        public void Test1_SingleOperation(
            [Values("LoadDataFirstWay", "LoadDataSecondWay")]
            string loadMethod,
            [Values("UpdataDataFirstWay", "UpdateDataSecondWay", "UpdateDataThirdWay", "UpdateDataFourthWay")]
            string updateMethod,
            [Values("checkDataResultChangedI", "checkDataResultChangedJ", "checkDataResultSingleOperationI", "checkDataResultSingleOperationJ")]
            string checkMethod){

            Operation boxCover = new Operation();

            //load
            boxCover.Run(loadMethod);

            //update
            boxCover.Run(updateMethod);

            //check
            boxCover.Run(checkMethod);
        }

        [Test, Combinatorial]
        [Property("TambourineArguments", "loadMethod,updateMethodFirst,updateMethodSecond,checkMethod")]
        [Property("TambourineColumn", "checkMethod")]
        public void Test2_PairOperation(
            [Values("LoadDataFirstWay", "LoadDataSecondWay")]
            string loadMethod,
            [Values("UpdataDataFirstWay", "UpdateDataSecondWay", "UpdateDataThirdWay", "UpdateDataFourthWay")]
            string updateMethodFirst,
            [Values("UpdataDataFirstWay", "UpdateDataSecondWay", "UpdateDataThirdWay", "UpdateDataFourthWay")]
            string updateMethodSecond,
            [Values("checkDataResultChangedI", "checkDataResultChangedJ", "checkDataResultPairOperationI", "checkDataResultPairOperationJ")]
            string checkMethod)
        {

            Operation boxCover = new Operation();

            //load
            boxCover.Run(loadMethod);

            //update
            boxCover.Run(updateMethodFirst);
            boxCover.Run(updateMethodSecond);

            //check
            boxCover.Run(checkMethod);
        }

        [Test, Combinatorial]
        [Property("TambourineArguments", "loadMethod,updateMethodFirst,updateMethodSecond,updateMethodThird,checkMethod")]
        [Property("TambourineColumn", "checkMethod")]
        public void Test3_ThreeOperation(
            [Values("LoadDataFirstWay", "LoadDataSecondWay")]
            string loadMethod,
            [Values("UpdataDataFirstWay", "UpdateDataSecondWay", "UpdateDataThirdWay", "UpdateDataFourthWay")]
            string updateMethodFirst,
            [Values("UpdataDataFirstWay", "UpdateDataSecondWay", "UpdateDataThirdWay", "UpdateDataFourthWay")]
            string updateMethodSecond,
            [Values("UpdataDataFirstWay", "UpdateDataSecondWay", "UpdateDataThirdWay", "UpdateDataFourthWay")]
            string updateMethodThird,
            [Values("checkDataResultChangedI", "checkDataResultChangedJ", "checkDataResultThreeOperationI", "checkDataResultThreeOperationJ")]
            string checkMethod)
        {

            Operation boxCover = new Operation();

            //load
            boxCover.Run(loadMethod);

            //update
            boxCover.Run(updateMethodFirst);
            boxCover.Run(updateMethodSecond);
            boxCover.Run(updateMethodThird);

            //check
            boxCover.Run(checkMethod);
        }

    }
}
